/***************************************************
> Copyright (C) 2024 ==QWZL== All rights reserved.
> File Name: safety_man.c
> Author: nan
> Mail:w1468950374@163.com
> Created Time: 2024年11月18日 星期一 15时35分29秒
***************************************************/
#include "safety_man.h"

int sock = 0; // 客户端的 socket

// 安全员登录验证
int user_login(char *accounts, char *password)
{
    printf("\t*************************************\n");
    printf("\t*******\t矿用安全巡检系统\t*****\n");
    printf("\t****\t请输入账号密码进行登录...****\n");
    printf("\t*************************************\n");
    printf("账号：\n");
    scanf("%s", accounts);
    printf("密码：\n");
    scanf("%s", password);
    sleep(2);
    return 0;
}

int create_socket()
{
    int sock = 0;
    int ret = 0;
    struct sockaddr_in addr;

    // 设置服务器地址
    addr.sin_family = AF_INET;
    addr.sin_port = htons(6999);
    addr.sin_addr.s_addr = inet_addr("47.99.97.66");

    // 创建套接字
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1)
    {
        LOG_E("socket");
        exit(-1);
    }

    // 发生连接请求
    ret = connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    if (ret == -1)
    {
        LOG_E("connect");
        close(sock); // 连接失败后关闭套接字
        exit(-1);
    }
    return sock;
}
// 发送账号和密码到服务器并得到服务器的回应
int send_info(char *accounts, char *password)
{
    Login inf_msg = LOGIN__INIT;
    inf_msg.username = accounts;
    inf_msg.passwd = password;

    // 序列化 Protobuf 数据
    unsigned long len = login__get_packed_size(&inf_msg); // 获取序列化后数据的大小
    uint8_t *buf = malloc(len);
    if (!buf)
    {
        LOG_E("malloc");
        exit(-1);
    }
    login__pack(&inf_msg, buf); // 序列化数据到 buf

    // 创建包含登录数据的 All 消息
    All all_msg = ALL__INIT;
    all_msg.type = "login";
    all_msg.payload.len = len;
    all_msg.payload.data = buf; // 将登录消息的序列化数据赋给 payload.data

    // 获取 All 消息的序列化数据大小
    size_t all_size = all__get_packed_size(&all_msg);
    //printf("all_size: %ld\n", all_size); // 修正了打印大小的格式化符号
    uint8_t *all_buf = malloc(all_size);
    if (!all_buf)
    {
        LOG_E("malloc");
        free(buf); // 释放之前分配的内存
        exit(-1);
    }
    all__pack(&all_msg, all_buf); // 序列化 All 消息到 all_buf
    
    // 打印日志消息
    LOG_I("probuf组包成功\n");  

    // 发送数据到服务器
    sock = create_socket(); // 假设 create_socket() 正常工作
    if (sock == -1)
    {
        LOG_E("create_socket");
        free(buf);
        free(all_buf);
        exit(-1);
    }

    // 发送序列化后的 All 消息
    int ret = send(sock, all_buf, all_size, 0);
    free(buf);     // 发送完后释放内存
    free(all_buf); // 发送完后释放内存
    if (ret == -1)
    {
        LOG_E("send");
        close(sock); // 关闭 socket
        exit(-1);
    }

    // 打印日志消息
    LOG_I("客户端成功发送安全员账号信息\n");  // 打印用户名

    char value[200] = {0};
    ret = recv(sock, value, sizeof(value), 0);
    if (ret == -1)
    {
        LOG_E("recv");
        exit(1);
    }
    printf("%s\n", value); // 服务器返回判断是否登录成功的字符串
    
    ret = strcmp(value, "登录成功");
    // 打印日志消息
    LOG_I("服务器回应：登录成功\n");

    close(sock); // 发送完成后关闭 socket
    return ret;
}

// 数据发送
int send_data(char *data_buf,unsigned long l)
{
    char buf[20] = {0};
    // 发送数据到服务器
    int sock = create_socket();
    if (sock == -1)
    {
        perror("create_socket");
        exit(-1);
    }
    //printf("l:%ld\n", l);
    int ret = send(sock, data_buf, l, 0);
    if (ret == -1)
    {
        LOG_E("send");
        close(sock); // 关闭 socket
        exit(-1);
    }
    printf("发送成功!\n");
    
    // 打印日志消息
    LOG_I("客户端成功发送采集数据\n");

    recv_data();                   // 接收服务器返回的结果
    ret = strcmp(buf, "上传成功"); // 判断是否上传成功

    // 打印日志消息
    LOG_I("服务器回应：环境数据采集成功\n");

    close(sock);                   // 发送完成后关闭 socket
    return ret;
}

// 接受采集数据

int recv_data()
{
    char buf[1024] = {0};
    int ret = 0;
    ret = recv(sock, buf, sizeof(buf) - 1, 0);
    if (ret == -1)
    {
        LOG_E("接收数据失败");
        return -1;
    }
    printf("接收到的数据为：%s\n", buf);
    
    // 打印日志消息
    LOG_I("服务器接收到的数据为：%s\n", buf);

    return 0;
}

// 设备功能菜单
int equipment_menu()
{
    int choice = 0;
    char data_buf[1024] = {0};
    unsigned long l = 0;
    while (1)
    {
        printf("\t*************************************\n");
        printf("\t****\t矿用安全巡检系统\t****\n");
        printf("\t\t请选择您要进行的操作...\n");
        printf("\t*************************************\n");
        printf("1.数据采集\n");
        printf("2.数据发送\n");
        printf("3.退出\n");
        printf("请输入您的选择：\n");
        scanf("%d", &choice);
        switch (choice)
        {
        case 1:
            data_collection(data_buf,&l);
            printf("l1:%ld\n", l);
            break;
        case 2:
            printf("l2:%ld\n", l);
            send_data(data_buf,l);
            break;
        case 3:
            exit(0);
            break;
        default:
            printf("输入错误，请重新输入！\n");
            break;
        }
    }
    return 0;
}

// 数据采集
int data_collection(char *str,unsigned long *l)
{
    DATA data;
    printf("\t*************************************\n");
    printf("\t****\t数据采集\t****\n");
    printf("\t\t请输入您要采集的数据...\n");
    printf("\t*************************************\n");
    printf("请输入甲烷值：\n");
    scanf("%f", &data.CH4);
    printf("请输入一氧化碳值：\n");
    scanf("%f", &data.CO);
    printf("请输入二氧化碳值：\n");
    scanf("%f", &data.CO2);
    printf("请输入氧气值：\n");
    scanf("%f", &data.O2);
    printf("请输入大气压：\n");
    scanf("%f", &data.atmosphere);
    printf("请输入温度：\n");
    scanf("%f", &data.temperature);
    printf("请输入湿度：\n");
    scanf("%f", &data.RH);

    // 时间戳
    struct tm *p;       // 一个指向tm结构体的指针，用于存储时间数据
    char date_str[100]; // 存储生成的内容
    time_t currentTime = time(NULL);
    if (currentTime == -1)
    {
        perror("time");
        exit(1);
    }
    p = localtime(&currentTime); // 转换为本地时间
    if (p == NULL)
    {
        perror("localtime");
        exit(1);
    }
    // 提取当前时间的年/月/日/时/分/秒
    int year = p->tm_year + 1900; // tm_year是自1900年以来的年数，要加上1900
    int month = p->tm_mon + 1;    // tm_mon的范围是0-11，要加上1
    int day = p->tm_mday;
    int hour = p->tm_hour;
    int min = p->tm_min;
    int sec = p->tm_sec;

    // 存放时间格式化字符串
    sprintf(date_str, "%04d.%02d.%02d.%02d.%02d", year, month, day, hour, min);
    // 将时间戳写入数据
    strcpy(data.date, date_str);

    // 获取采集人员信息
    printf("请输入采集人员姓名:\n");
    scanf("%s", data.collecter);

    // 判断采集点
    printf("请输入您现在所处的采集数据点\n");
    scanf("%s", data.location);

    // 判断数据结果（是否超标）
    //strcpy(data.judge_result, "数据正常");
    int alarm = alarm_setting(&data);

    // probuf组包
    InputInformation data_msg = INPUT_INFORMATION__INIT;

    data_msg.ch4 = data.CH4;
    data_msg.co = data.CO;
    data_msg.co2 = data.CO2;
    data_msg.o2 = data.O2;
    data_msg.atmosphere = data.atmosphere;
    data_msg.temperature = data.temperature;
    data_msg.rh = data.RH;
    data_msg.date = malloc(200);
    strcpy(data_msg.date, data.date);
    data_msg.collecter = malloc(50);
    strcpy(data_msg.collecter, data.collecter);
    data_msg.place = malloc(50);
    strcpy(data_msg.place, data.location);
    data_msg.judge_result = malloc(500);
    strcpy(data_msg.judge_result, data.judge_result);

    // 打包数据
     unsigned long data_size = input_information__get_packed_size(&data_msg);
     uint8_t *data_buf = malloc(data_size);
     input_information__pack(&data_msg, data_buf);
    // printf("len1:%ld\n",data_size);
     // 再次打包到All
     All all_msg = ALL__INIT;
     all_msg.type = "input_information";
     all_msg.payload.data = data_buf;
     all_msg.payload.len = data_size;
     unsigned int all_size = all__get_packed_size(&all_msg);
     uint8_t *all_buf = malloc(all_size);
     all__pack(&all_msg, all_buf);  // 全部数据+type
     //printf("all_buf大小:%d\n", all_size);    // 打印数据大小
     *l = all_size;
     memcpy(str, all_buf, all_size);   // 复制到str中
     // 释放内存
     free(data_msg.date);
     free(data_msg.collecter);
     free(data_msg.place);
     free(data_msg.judge_result);
     free(data_buf);
     free(all_buf);

     return 0;
}

// 报警设置
int alarm_setting(DATA *data)
{
    printf("\t*************************************\n");
    printf("\t\t****\t报警设置\t****\n");
    printf("\t*************************************\n");
    int alarm = 0;
    // 检查甲烷浓度是否超出警戒值
    memset(data->judge_result, 0,sizeof(data->judge_result));
    if (data->CH4 > 1.0)
    {
        printf("\033[31m警告：甲烷浓度超标，请注意！\033[0m\n");
        strcat(data->judge_result, "甲烷浓度超标！");
        
        // 打日志消息
        LOG_I("采集数据甲烷浓度超标！\n");

        alarm = 1;
    }
    // 检查一氧化碳浓度是否超过警戒值
    if (data->CO > 0.01)
    {
        printf("\033[31m警告：一氧浓度超标，请注意！\033[0m\n");
        strcat(data->judge_result, "CO浓度超标！");

        // 打印日志消息
        LOG_I("采集数据CO浓度超标！\n");

        alarm = 1;
    }
    // 检查二氧化碳浓度是否超过警戒值
    if (data->CO2 > 1.0)
    {
        printf("\033[31m警告：二氧浓度超标，请注意！\033[0m\n");
        strcat(data->judge_result, "CO2浓度超标！");
       
        // 打印日志消息
        LOG_I("采集数据CO2浓度超标！\n");

        alarm = 1;
    }
    // 检查氧气浓度是否超过警戒值
    if (data->O2 < 18.0)
    {
        printf("\033[31m警告：氧气浓度不足，请注意！\033[0m\n");
        strcat(data->judge_result, "氧气浓度不足！");
       
        // 打印日志消息
        LOG_I("采集数据氧气浓度不足！\n");

        alarm = 1;
    }
    // 检查大气压是否超过警戒值
    if (data->atmosphere < 1000.0)
    {
        printf("\033[31m警告：大气压过低，请注意！\033[0m\n");
        strcat(data->judge_result, "大气压过低！");

        // 打印日志消息
        LOG_I("采集数据大气压过低！\n");

        alarm = 1;
    }
    // 检查温度是否超过警戒值
    if (data->temperature > 30.0)
    {
        printf("\033[31m警告：温度过高，请注意！\033[0m\n");
        strcat(data->judge_result, "温度过高！");

        // 打印日志消息
        LOG_I("采集数据温度过高！\n");

        alarm = 1;
    }
    // 检查湿度是否超过警戒值
    if (data->RH > 80.0)
    {
        printf("\033[31m警告：湿度过高，请注意！\033[0m\n");
        strcat(data->judge_result, "湿度过高！");

        // 打印日志消息
        LOG_I("采集数据湿度过高！\n");

        alarm = 1;
    }
    strcat(data->judge_result, "\0");
    printf("%ld\n",strlen(data->judge_result));
    printf("%s\n",data->judge_result);//错误信息长度
    // 如果有任何报警触发，返回1，表示触发报警
    if (alarm == 1)
    {
        return 1;
    }

    // 如果没有触发报警，返回0
    return 0;
}
